﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.DataAccess.Client;
using System.Data.Common;
using System.Reflection;
using System.Data.DataModel;

namespace System.Data.DataControl
{
    public class OracleController : DbController
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        public override void SetCommand()
        {
            this.command = new Oracle.DataAccess.Client.OracleCommand();
            this.command.Connection =  DataConnection.Connection;
            ((OracleCommand)this.command).BindByName = true;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override DbDataReader GetDataReader()
        {
            return (OracleDataReader)this.command.ExecuteReader();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public override void SetParameters(object obj, string[] primaryKey)
        {
            Type type = obj.GetType();
            Array.ForEach<PropertyInfo>(type.GetProperties(), delegate(PropertyInfo property)
            {
                string pkPropertyName = String.Empty;
                if (primaryKey != null)
                {
                    foreach (string pkProperty in primaryKey)
                    {
                        if (property.Name.Equals(pkProperty))
                        {
                            return;
                        }
                    }
                }

                this.SetParameter(property, obj);

            });
        }

        public override void SetParameter(PropertyInfo property, object obj)
        {
            this.command.Parameters.Add(new OracleParameter(property.Name, property.GetValue(obj, null)));
        }

        public override void SetParameter(string parameterName, object parameterValue)
        {
            this.command.Parameters.Add(new OracleParameter(parameterName, parameterValue));
        }

        public override int CreateTable(bool dropTable, string className, List<PropertySet> properties, string filePath)
        {

            StringBuilder builder = new StringBuilder();
            StringBuilder pkBuilder = new StringBuilder();
            if (dropTable)
            {
               
                this.command.Parameters.Add(new OracleParameter("TABLE_NAME", className.ToUpper()));
                this.command.CommandText = "Select * From USER_TABLES Where TABLE_NAME = :TABLE_NAME";
                
                OracleDataReader reader = (OracleDataReader)this.GetDataReader();
                
                while (reader.Read())
                {
                    this.command.CommandText = "DROP TABLE " + className;
                    this.command.ExecuteNonQuery();
                }
                this.command.Parameters.Clear();
                this.command.Connection.Close();
                
               
            }

            builder.AppendLine("CREATE TABLE " + className + " ");

            builder.AppendLine("(");

            int pkCount = 0;
            properties.ForEach(delegate(PropertySet property)
            {
                builder.Append("\t" + property.Name + " ");
                builder.Append(
                    property.Type.Name.Equals(typeof(System.Int32).Name) ? "NUMBER (" + property.Size.ToString() + ")" :
                    property.Type.Name.Equals(typeof(System.Int64).Name) ? "NUMBER (" + property.Size.ToString() + ")" :
                    property.Type.Name.Equals(typeof(System.DateTime).Name) ? "DATE" :
                    property.Type.Name.Equals(typeof(System.Boolean).Name) ? "NUMBER (" + property.Size.ToString() + ")" :
                    property.Type.Name.Equals(typeof(System.Double).Name) ? "NUMBER (" + property.Size.ToString() + ",2)" :
                    "VARCHAR2" + "(" + property.Size.ToString() + ")"
                    );

                if (property.PrimaryKey)
                {
                    builder.Append("NOT NULL");
                    pkBuilder.Append( property.Name + ",");
                    pkCount++;
                }
                builder.Append(",\r\n");
            });
            if (pkCount > 0)
            {
                pkBuilder.Remove(pkBuilder.Length - 1, 1);
                builder.AppendLine("\t\tCONSTRAINT " + className + "_PK PRIMARY KEY (" + pkBuilder.ToString() + ") USING INDEX ");
                builder.AppendLine("\t\tPCTFREE 10 ");
                builder.AppendLine("\t\tINITRANS 2 ");
                builder.AppendLine("\t\t MAXTRANS 255 ");
                builder.AppendLine("\t\tTABLESPACE USERS ");
                builder.AppendLine("\t\tSTORAGE(INITIAL 64K NEXT 1M MINEXTENTS 1 MAXEXTENTS 2147483645 BUFFER_POOL DEFAULT) ");
                builder.AppendLine("\t\tLOGGING ");
                builder.AppendLine("\t\tENABLE ");
            }
            builder.AppendLine("\t) ");
            builder.AppendLine("\tPCTFREE 10 ");
            builder.AppendLine("\tMAXTRANS 255 ");
            builder.AppendLine("\tTABLESPACE USERS ");
            builder.AppendLine("\tSTORAGE(INITIAL 64K NEXT 1M MINEXTENTS 1 MAXEXTENTS 2147483645 BUFFER_POOL DEFAULT) ");
            builder.AppendLine("\tNOCACHE");
            builder.AppendLine("\tLOGGING");

            this.command.CommandText = builder.ToString();
            return base.CreateTable(dropTable, className, properties, filePath);
        }


        #region Constructor
        public OracleController()
        {
            this.SetCommand();
        }

        #endregion


    }
}
